//
// Created by limdzh on 25-7-11.
//

#include "log_system.h"

Log_system log_system = {
        .log_system_state = WAIT_FILE_SYSTEM_IDLE,
				.next_state = WAIT_FILE_SYSTEM_IDLE,
				.new_create = false,
                .start_monitor = false,
                .now_cnt = 0,
                .send_delay = 10
};

Setting_variables setting_variables = {
				.now_num = 0
};

Monitor_Var monitor_var = {
	.now_num = 0
};

int a = 0;

uint8_t watch_data[10];

bool update_flight_log_id(void *arg){
	(void)arg;
	bool ret = false;
	uint16_t last_log_id = file_system.loader_info.file_num - 1;
	uint8_t raw_data[2] = {last_log_id & 0xFF, (last_log_id >> 8) & 0xFF}; 
	File_Struct temp_file = open_file(BY_BOTH, SETTINGS_FILE, 0);
	File_Struct fli_file = open_file(BY_BOTH, FLIGHT_FILE, last_log_id);
	if(temp_file.init_if && temp_file.file_state == OPEN && fli_file.init_if && fli_file.file_state == OPEN){
		if(NOW_FLIGHT_LOG_ID < setting_variables.now_num){
			uint8_t this_time_data_size = SIZEOF(setting_variables.pack[NOW_FLIGHT_LOG_ID].type);
			uint16_t file_offset = get_setting_index_offset(NOW_FLIGHT_LOG_ID);
			file_write_at(&temp_file, &raw_data[0], this_time_data_size, 2 + file_offset);
			now_flight_log_id = last_log_id;
			watch_data[0] = this_time_data_size;
			watch_data[1] = file_offset;
			watch_data[2] = last_log_id;
			ret = true;
			log_system.log_system_state = PARAM_INIT;
		}
	}
	return ret;
}

void log_system_auto(void){
    if(log_system.log_system_state == WAIT_FILE_SYSTEM_IDLE){
        if(file_system.file_system_state == FILE_SYSTEM_IDLE){
            log_system.next_state = CHECK_LOG_SYSTEM;
        }
    }else if(log_system.log_system_state == CHECK_LOG_SYSTEM){
        if(file_system.loader_info.file_num == 0){
            create_file(SETTINGS_FILE);
						uint8_t write_buf[2] = {0x00, 0x00};
						File_Struct temp_file = open_file(BY_ID, SETTINGS_FILE, 0);
						if(temp_file.init_if && temp_file.file_loader_info.file_type == SETTINGS_FILE){
							file_write(&temp_file, &write_buf[0], 2);
						}
						close_file(&temp_file);
						log_system.new_create = true;
						
						create_file(NORMAL_FILE);
						create_file(FLIGHT_FILE);
						
						log_system.next_state = CHECK_LOG_SYSTEM;
        }else{
            File_Struct temp_file = open_file(BY_ID, SETTINGS_FILE, 0);
						Piece_memory_Info piece_mem_info = get_piece_info(0);
            if(temp_file.init_if && temp_file.file_loader_info.file_type == SETTINGS_FILE){
							if(piece_mem_info.piece_usages == 0x04){
								uint8_t write_buf[2] = {0x00, 0x00};
								file_write(&temp_file, &write_buf[0], 2);
								log_system.next_state = WRITE_INIT_PARAM;
							}else{
								log_system.next_state = log_system.new_create?WRITE_INIT_PARAM:PARAM_INIT;
							}
            }else{
                format_all_files();
								log_system.next_state = CHECK_LOG_SYSTEM;
						}
						close_file(&temp_file);
        }
    }else if(log_system.log_system_state == WRITE_INIT_PARAM){ // raw_data[8]
				File_Struct setting_file = open_file(BY_ID, SETTINGS_FILE, 0);
				if(setting_file.init_if && setting_file.file_state == OPEN){
					for(int i=0;i < setting_variables.now_num; i++){
						uint8_t raw_data[9] = {0x00};
						memcpy(&raw_data[0], (void*)setting_variables.pack[i].ram_addr, SIZEOF(setting_variables.pack[i].type));
						memcpy(&watch_data[0], &raw_data[0], 9);
						watch_data[9] = SIZEOF(setting_variables.pack[i].type);
						file_write(&setting_file, &raw_data[0], SIZEOF(setting_variables.pack[i].type));
					}
					uint8_t var_num_data[2] = {(setting_variables.now_num & 0xFF), ((setting_variables.now_num >> 8) & 0xFF)};
					file_write_at(&setting_file, &var_num_data[0], 0, 2);
					close_file(&setting_file);
					log_system.next_state = LOG_SYSTEM_IDLE;
				}
    }else if(log_system.log_system_state == PARAM_INIT){
				uint16_t file_offset = 2;
				File_Struct setting_file = open_file(BY_ID, SETTINGS_FILE, 0);
			  if(setting_file.init_if && setting_file.file_state == OPEN){
					uint8_t read_buf[8];
					for(int i=0;i< setting_variables.now_num;i++){
						uint8_t this_size = SIZEOF(setting_variables.pack[i].type);
						file_read(&setting_file, &read_buf[0], file_offset, this_size);
						Register_Var_Name now_name = setting_variables.pack[i].reg_var_name;
						UPDATE_PARAM(now_name, i, setting_variables.pack[i].type, &read_buf[0]);
						file_offset += this_size;
					}
					File_Struct flight_file = open_file(BY_BOTH, FLIGHT_FILE, now_flight_log_id);
						if(flight_file.init_if && flight_file.file_state == OPEN){
							if(flight_file.file_ptr_offset > 0){
								create_file(FLIGHT_FILE);
								now_flight_log_id = file_system.loader_info.file_num - 1;
								REGISTER_FUNC(&update_flight_log_id, 1000);
							}
						}
					log_system.next_state = LOG_SYSTEM_IDLE;
				}
		}else if(log_system.log_system_state == LOG_SYSTEM_IDLE){
			if(file_system.file_system_state == FILE_SYSTEM_INIT){
				log_system.log_system_state = WAIT_FILE_SYSTEM_IDLE;
			}else{
                if(log_system.start_record){
                    log_system.start_record = false;
                }
                if(log_system.start_monitor){
                    log_system.now_cnt ++;
                    if(log_system.now_cnt >= log_system.send_delay) {
                        send_monitor_variable_packs();
                    }
                    log_system.now_cnt %= log_system.send_delay;
                }
            }


		}
		log_system.log_system_state = log_system.next_state;
}

void send_monitor_variable_packs(){
    uint16_t data_total_len = 0;
    log_system.send_buf[0] = SEND_HEADER;
    log_system.send_buf[1] = SEND_ID_ONLINE_MONITOR;
    for(int i=0;i< monitor_var.now_num; i++){
        uint8_t this_len = SIZEOF(monitor_var.monitor_vars[i].type);
        if(data_total_len + this_len > 256){
            break;
        }else{
            memcpy(&log_system.send_buf[2 + data_total_len], (void*)monitor_var.monitor_vars[i].ram_addr, this_len);
            data_total_len += this_len;
        }
    }
    log_system.send_buf[2 + data_total_len] = SEND_TAIL;
    if(log_system.data_from_raw == 0){ // USART
        huart_send(&huart1_usart_handle, log_system.send_buf, 3 + data_total_len);
    }else{
        usb_data_send(log_system.send_buf, 3 + data_total_len);
    }
}

void normal_log_file_write(Log_Info_State info_state, uint8_t* strs, uint16_t str_len){
	File_Struct file = open_file(BY_BOTH, NORMAL_FILE, now_normal_log_id);
	if(file.init_if && file.file_state == OPEN){
		uint8_t heads[10] = {0x00};
		uint8_t head_lens = 0;
		if(info_state == LOG_INFO){
			heads[0] = '[';
			heads[1] = 'I';
			heads[2] = 'N';
			heads[3] = 'F';
			heads[4] = 'O';
			heads[5] = ']';
			heads[6] = ':';
			head_lens = 7;
		}else if(info_state == LOG_WARNING){
			heads[0] = '[';
			heads[1] = 'W';
			heads[2] = 'A';
			heads[3] = 'R';
			heads[4] = 'N';
			heads[5] = 'I';
			heads[6] = 'N';
			heads[7] = 'G';
			heads[8] = ']';
			heads[9] = ':';
			head_lens = 10;
		}else if(info_state == LOG_ERROR){
			heads[0] = '[';
			heads[1] = 'E';
			heads[2] = 'R';
			heads[3] = 'R';
			heads[4] = 'O';
			heads[5] = 'R';
			heads[6] = ']';
			heads[7] = ':';
			head_lens = 8;
		}
		file_write(&file, &heads[0], head_lens);
		file_write_lines(&file, &strs[0], str_len);
		close_file(&file);
	}
}

void REGISTER_PARAM(uint32_t var_ram_addr, Variable_TYPE var_type, Register_Var_Name reg_name){
	if(setting_variables.now_num < MAX_PARAM_NUM){
		Variable_pack temp_pack = {.type = var_type, .reg_var_name = reg_name, .ram_addr = var_ram_addr};
		setting_variables.pack[setting_variables.now_num] = temp_pack;
		setting_variables.now_num ++;
	}
}

void UPDATE_PARAM(Register_Var_Name reg_name, uint16_t index, Variable_TYPE type, uint8_t* raw_data){
	if(setting_variables.pack[index].reg_var_name == reg_name){
		memcpy((void*)setting_variables.pack[index].ram_addr, raw_data, SIZEOF(type));
	}
}

void MONITOR_VARIABLE(uint32_t var_ram_addr, Variable_TYPE var_type, Monitor_Var_Name reg_name){
    if(monitor_var.now_num < MAX_MONITOR_VAR_NUM){
        Monitor_pack  temp_pack = {.type = var_type, .mon_var_name = reg_name, .ram_addr = var_ram_addr};
        monitor_var.monitor_vars[monitor_var.now_num] = temp_pack;
        monitor_var.now_num ++;
    }
}

uint16_t get_setting_index_offset(uint16_t index){
    if(index < setting_variables.now_num){
        return setting_variables.index_to_offset[index];
    }
    return 0;
}

uint16_t get_monitor_index_offset(uint16_t index){
    if(index < monitor_var.now_num){
        return monitor_var.index_to_offset[index];
    }
    return 0;
}

void update_param_data(uint8_t* raw_data, uint8_t data_len){
	uint8_t now_offset = 0;
	if(data_len >0){
		File_Struct temp_file = open_file(BY_ID, SETTINGS_FILE, 0);
		if(temp_file.init_if && temp_file.file_state == OPEN){
			uint8_t temp_data[8] = {0x00};
			while(now_offset < data_len){
				uint8_t var_index = raw_data[now_offset];
				now_offset += 1;
				if(var_index < setting_variables.now_num){
					uint8_t this_time_data_size = SIZEOF(setting_variables.pack[var_index].type);
					if((Register_Var_Name)var_index == NOW_NORMAL_LOG_ID || (Register_Var_Name)var_index == NOW_FLIGHT_LOG_ID){
						now_offset += this_time_data_size;
						continue;
					}
					uint16_t file_offset = get_setting_index_offset(var_index);
					memcpy(&temp_data[0], &raw_data[now_offset], this_time_data_size);
					file_write_at(&temp_file, &temp_data[0], this_time_data_size, 2 + file_offset);
					now_offset += this_time_data_size;
				}
			}
			log_system.log_system_state = PARAM_INIT;
		}
	}	
}


